/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.gallery3d.data;

import android.content.Context;
import android.net.Uri;

import com.android.gallery3d.app.GalleryApp;
import com.android.gallery3d.ui.Log;

import java.util.ArrayList;
import java.util.HashSet;

public class ClusterAlbumSet extends MediaSet implements ContentListener {
	private static final String TAG = ClusterAlbumSet.class.getSimpleName();
	private GalleryApp mApplication;
	private MediaSet mBaseSet;
	private int mKind;
	private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>();
	private boolean mFirstReloadDone;

	public ClusterAlbumSet(Path path, GalleryApp application, MediaSet baseSet,
			int kind) {
		super(path, INVALID_DATA_VERSION);
		Log.d(TAG, "ClusterAlbumSet");
		mApplication = application;
		mBaseSet = baseSet;
		mKind = kind;
		baseSet.addContentListener(this);
	}

	@Override
	public MediaSet getSubMediaSet(int index) {
		Log.d(TAG, "getSubMediaSet -- index : " + index);
		return mAlbums.get(index);
	}

	@Override
	public int getSubMediaSetCount() {
		return mAlbums.size();
	}

	@Override
	public String getName() {
		return mBaseSet.getName();
	}

	@Override
	public long reload() {
		Log.d(TAG, "reload");
		if (mBaseSet.reload() > mDataVersion) {
			if (mFirstReloadDone) {
				updateClustersContents();
			} else {
				updateClusters();
				mFirstReloadDone = true;
			}
			mDataVersion = nextVersionNumber();
		}
		return mDataVersion;
	}

	@Override
	public void onContentDirty() {
		notifyContentChanged();
	}

	private void updateClusters() {
		Log.d(TAG, "updateClusters");
		mAlbums.clear();
		Clustering clustering;
		Context context = mApplication.getAndroidContext();
		switch (mKind) {
		case ClusterSource.CLUSTER_ALBUMSET_TIME:
			Log.d(TAG, "Kind : TIME");
			clustering = new TimeClustering(context);
			break;
		case ClusterSource.CLUSTER_ALBUMSET_LOCATION:
			Log.d(TAG, "Kind : LOCATION");
			clustering = new LocationClustering(context);
			break;
		case ClusterSource.CLUSTER_ALBUMSET_TAG:
			Log.d(TAG, "Kind : TAG");
			clustering = new TagClustering(context);
			break;
		case ClusterSource.CLUSTER_ALBUMSET_FACE:
			Log.d(TAG, "Kind : FACE");
			clustering = new FaceClustering(context);
			break;
		default: /* CLUSTER_ALBUMSET_SIZE */
			Log.d(TAG, "Kind : SIZE");
			clustering = new SizeClustering(context);
			break;
		}

		clustering.run(mBaseSet);
		int n = clustering.getNumberOfClusters();
		Log.d(TAG, "getNumberOfClusters: " + n);
		DataManager dataManager = mApplication.getDataManager();
		for (int i = 0; i < n; i++) {
			Path childPath;
			String childName = clustering.getClusterName(i);
			if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) {
				childPath = mPath.getChild(Uri.encode(childName));
			} else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) {
				long minSize = ((SizeClustering) clustering).getMinSize(i);
				childPath = mPath.getChild(minSize);
			} else {
				childPath = mPath.getChild(i);
			}

			ClusterAlbum album;
			synchronized (DataManager.LOCK) {
				album = (ClusterAlbum) dataManager.peekMediaObject(childPath);
				if (album == null) {
					album = new ClusterAlbum(childPath, dataManager, this);
				}
			}
			album.setMediaItems(clustering.getCluster(i));
			album.setName(childName);
			album.setCoverMediaItem(clustering.getClusterCover(i));
			mAlbums.add(album);
		}
	}

	private void updateClustersContents() {
		Log.d(TAG, "updateClustersContents");
		final HashSet<Path> existing = new HashSet<Path>();
		mBaseSet.enumerateTotalMediaItems(new ItemConsumer() {
			@Override
			public void consume(int index, MediaItem item) {
				existing.add(item.getPath());
			}
		});

		int n = mAlbums.size();

		// The loop goes backwards because we may remove empty albums from
		// mAlbums.
		//循环遍历，删除空的Albums
		for (int i = n - 1; i >= 0; i--) {
			ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems();
			ArrayList<Path> newPaths = new ArrayList<Path>();
			int m = oldPaths.size();
			for (int j = 0; j < m; j++) {
				Path p = oldPaths.get(j);
				if (existing.contains(p)) {
					newPaths.add(p);
				}
			}
			mAlbums.get(i).setMediaItems(newPaths);
			if (newPaths.isEmpty()) {
				mAlbums.remove(i);
			}
		}
	}
}
